home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 1 / Cream of the Crop 1.iso / PROGRAM / DJINC106.ARJ / FIX24.H < prev    next >
C/C++ Source or Header  |  1992-03-29  |  12KB  |  586 lines

  1. // This may look like C code, but it is really -*- C++ -*-
  2. /* 
  3. Copyright (C) 1988 Free Software Foundation
  4.     written by Kurt Baudendistel (gt-eedsp!baud@gatech.edu)
  5.     adapted for libg++ by Doug Lea (dl@rocky.oswego.edu)
  6.  
  7. This file is part of the GNU C++ Library.  This library is free
  8. software; you can redistribute it and/or modify it under the terms of
  9. the GNU Library General Public License as published by the Free
  10. Software Foundation; either version 2 of the License, or (at your
  11. option) any later version.  This library is distributed in the hope
  12. that it will be useful, but WITHOUT ANY WARRANTY; without even the
  13. implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  14. PURPOSE.  See the GNU Library General Public License for more details.
  15. You should have received a copy of the GNU Library General Public
  16. License along with this library; if not, write to the Free Software
  17. Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  18. */
  19.  
  20. #ifndef _Fix24_h
  21. #ifdef __GNUG__
  22. #pragma interface
  23. #endif
  24. #define _Fix24_h 1
  25.  
  26. #include <stream.h>
  27. #include <std.h>
  28.  
  29. // extra type definitions 
  30.  
  31. typedef struct {
  32.   long                 u;
  33.   unsigned long           l;
  34. } twolongs;
  35.  
  36. // constant definitions
  37.  
  38. static const int
  39.   Fix24_shift = 31;
  40.           
  41. static const double
  42.   Fix24_fs = 2147483648.,        // 2^Fix24_shift
  43.   Fix24_mult = Fix24_fs,
  44.   Fix24_div = 1./Fix24_fs,
  45.   Fix24_max = 1. - .5/Fix24_fs,
  46.   Fix24_min = -1.;
  47.       
  48. static const unsigned long
  49.   Fix24_msb = 0x80000000L,
  50.   Fix24_lsb = 0x00000100L,
  51.   Fix24_m_max = 0x7fffff00L,
  52.   Fix24_m_min = 0x80000000L;
  53.  
  54. static const double
  55.   Fix48_fs = 36028797018963968.,    // 2^(24+Fix24_shift)
  56.   Fix48_max = 1. - .5/Fix48_fs,
  57.   Fix48_min = -1.,
  58.   Fix48_div_u = 1./Fix24_fs,
  59.   Fix48_div_l = 1./Fix48_fs;
  60.    
  61. static const twolongs
  62.   Fix48_msb = { 0x80000000L, 0L },
  63.   Fix48_lsb = { 0L, 0x00000100L },
  64.   Fix48_m_max = { 0x7fffff00L, 0xffffff00L },
  65.   Fix48_m_min = { 0x80000000L, 0L };
  66.           
  67. //
  68. // Fix24    class: 24-bit Fixed point data type
  69. //
  70. //    consists of a 24-bit mantissa (sign bit & 23 data bits).
  71. //
  72.  
  73. class Fix24 
  74.   friend class          Fix48;
  75.  
  76.   long                  m;
  77.  
  78.   long                  assign(double d);
  79.          operator       double();
  80.                         Fix24(long i);
  81.                         Fix24(int i);
  82.  
  83.  
  84. public:
  85.                         Fix24();
  86.                         Fix24(Fix24&  f);
  87.                         Fix24(double d);
  88.                         Fix24(Fix48& f);
  89.  
  90.                         ~Fix24();
  91.  
  92.   Fix24&                operator=(Fix24&  f);
  93.   Fix24&                operator=(double d);
  94.   Fix24&                operator=(Fix48& f);
  95.  
  96.   friend long&          mantissa(Fix24&  f);
  97.   friend double         value(Fix24&  f);
  98.  
  99.   Fix24                 operator +  ();
  100.   Fix24                 operator -  ();
  101.  
  102.   friend Fix24          operator +  (Fix24&  f, Fix24&  g);
  103.   friend Fix24          operator -  (Fix24&  f, Fix24&  g);
  104.   friend Fix48          operator *  (Fix24&  f, Fix24&  g);
  105.   friend Fix24          operator *  (Fix24&  f, int     g);
  106.   friend Fix24          operator *  (int     g, Fix24&  f);
  107.   friend Fix24          operator /  (Fix24&  f, Fix24&  g);
  108.   friend Fix24          operator << (Fix24&  f, int b);
  109.   friend Fix24          operator >> (Fix24&  f, int b);
  110.  
  111.   Fix24&                operator += (Fix24&  f);
  112.   Fix24&                operator -= (Fix24&  f);
  113.   Fix24&                operator *= (Fix24&  f);
  114.   Fix24&                operator *= (int     b);
  115.   Fix24&                operator /= (Fix24&  f);
  116.  
  117.   Fix24&                operator <<=(int b);
  118.   Fix24&                operator >>=(int b);
  119.  
  120.   friend int            operator == (Fix24&  f, Fix24&  g);
  121.   friend int            operator != (Fix24&  f, Fix24&  g);
  122.   friend int            operator >= (Fix24&  f, Fix24&  g);
  123.   friend int            operator <= (Fix24&  f, Fix24&  g);
  124.   friend int            operator >  (Fix24&  f, Fix24&  g);
  125.   friend int            operator <  (Fix24&  f, Fix24&  g);
  126.  
  127.   friend istream&       operator >> (istream& s, Fix24&  f);
  128.   friend ostream&       operator << (ostream& s, Fix24&  f);
  129.  
  130.   void                  overflow(long&);
  131.   void                  range_error(long&);
  132. };
  133.  
  134.  
  135. //
  136. // Fix48 class: 48-bit Fixed point data type
  137. //
  138. //    consists of a 48-bit mantissa (sign bit & 47 data bits).
  139. //
  140.  
  141. class Fix48 
  142.   friend class         Fix24;
  143.  
  144.   twolongs             m;
  145.  
  146.   twolongs             assign(double d);
  147.          operator      double();
  148.                        Fix48(twolongs i);
  149.  
  150. public:
  151.                        Fix48();
  152.                        Fix48(Fix48& f);
  153.                        Fix48(Fix24&  f);
  154.                        Fix48(double d);
  155.                        ~Fix48();
  156.  
  157.   Fix48&               operator =  (Fix48& f);
  158.   Fix48&               operator =  (Fix24&  f);
  159.   Fix48&               operator =  (double d);
  160.  
  161.   friend twolongs&     mantissa(Fix48& f);
  162.   friend double        value(Fix48& f);
  163.  
  164.   Fix48                operator +  ();
  165.   Fix48                operator -  ();
  166.  
  167.   friend Fix48         operator +  (Fix48& f, Fix48& g);
  168.   friend Fix48         operator -  (Fix48& f, Fix48& g);
  169.   friend Fix48         operator *  (Fix48& f, int    g);
  170.   friend Fix48         operator *  (int    g, Fix48& f);
  171.   friend Fix48         operator << (Fix48& f, int b);
  172.   friend Fix48         operator >> (Fix48& f, int b);
  173.  
  174.   friend Fix48         operator *  (Fix24&  f, Fix24&  g);
  175.  
  176.   Fix48&               operator += (Fix48& f);
  177.   Fix48&               operator -= (Fix48& f);
  178.   Fix48&               operator *= (int    b);
  179.   Fix48&               operator <<=(int b);
  180.   Fix48&               operator >>=(int b);
  181.  
  182.   friend int           operator == (Fix48& f, Fix48& g);
  183.   friend int           operator != (Fix48& f, Fix48& g);
  184.   friend int           operator >= (Fix48& f, Fix48& g);
  185.   friend int           operator <= (Fix48& f, Fix48& g);
  186.   friend int           operator >  (Fix48& f, Fix48& g);
  187.   friend int           operator <  (Fix48& f, Fix48& g);
  188.  
  189.   friend istream&      operator >> (istream& s, Fix48& f);
  190.   friend ostream&      operator << (ostream& s, Fix48& f);
  191.  
  192.   void                 overflow(twolongs& i);
  193.   void                 range_error(twolongs& i);
  194. };
  195.  
  196.  
  197. // active error handler declarations
  198.  
  199. typedef void (*Fix24_peh)(long&);
  200. typedef void (*Fix48_peh)(twolongs&);
  201.  
  202. extern Fix24_peh Fix24_overflow_handler;
  203. extern Fix48_peh Fix48_overflow_handler;
  204.  
  205. extern Fix24_peh Fix24_range_error_handler;
  206. extern Fix48_peh Fix48_range_error_handler;
  207.  
  208.  
  209. // error handler declarations
  210.  
  211. #if defined(SHORT_NAMES) || defined(VMS)
  212. #define    set_overflow_handler    sohndl
  213. #define set_range_error_handler    srnghdl
  214. #endif
  215.  
  216. extern Fix24_peh set_Fix24_overflow_handler(Fix24_peh);
  217. extern Fix48_peh set_Fix48_overflow_handler(Fix48_peh);
  218. extern void set_overflow_handler(Fix24_peh, Fix48_peh);
  219.  
  220. extern Fix24_peh set_Fix24_range_error_handler(Fix24_peh);
  221. extern Fix48_peh set_Fix48_range_error_handler(Fix48_peh);
  222. extern void set_range_error_handler(Fix24_peh, Fix48_peh);
  223.  
  224. extern void
  225.   Fix24_ignore(long&),
  226.   Fix24_overflow_saturate(long&),
  227.   Fix24_overflow_warning_saturate(long&),
  228.   Fix24_warning(long&),
  229.   Fix24_abort(long&);
  230.  
  231. extern void
  232.   Fix48_ignore(twolongs&),
  233.   Fix48_overflow_saturate(twolongs&),
  234.   Fix48_overflow_warning_saturate(twolongs&),
  235.   Fix48_warning(twolongs&),
  236.   Fix48_abort(twolongs&);
  237.  
  238.  
  239. inline Fix24::~Fix24() {}
  240.  
  241. inline Fix24::Fix24(long i)        
  242.   m = i; 
  243. }
  244.  
  245. inline Fix24::Fix24(int i)        
  246.   m = i; 
  247. }
  248.  
  249. inline Fix24::operator double() 
  250.   return  Fix24_div * m; 
  251. }
  252.  
  253. inline Fix24::Fix24()                 
  254.   m = 0; 
  255. }
  256.  
  257. inline Fix24::Fix24(Fix24&  f)        
  258.   m = f.m; 
  259. }
  260.  
  261. inline Fix24::Fix24(double d)        
  262. {
  263.   m = assign(d);
  264. }
  265.  
  266. inline Fix24::Fix24(Fix48& f)        
  267.   m = f.m.u;
  268. }
  269.  
  270. inline Fix24&  Fix24::operator=(Fix24&  f)    
  271.   m = f.m; 
  272.   return *this; 
  273. }
  274.  
  275. inline Fix24&  Fix24::operator=(double d) 
  276.   m = assign(d); 
  277.   return *this; 
  278. }
  279.  
  280. inline Fix24&  Fix24::operator=(Fix48& f)
  281.   m = f.m.u;
  282.   return *this; 
  283. }
  284.  
  285. inline long& mantissa(Fix24&  f)    
  286.   return f.m; 
  287. }
  288.  
  289. inline double value(Fix24&  f)        
  290.   return double(f); 
  291. }
  292.  
  293. inline Fix24 Fix24::operator+()         
  294.   return m; 
  295. }
  296.  
  297. inline Fix24 Fix24::operator-()         
  298.   return -m; 
  299. }
  300.  
  301. inline Fix24 operator+(Fix24&  f, Fix24&  g) 
  302. {
  303.   long sum = f.m + g.m;
  304.   if ( (f.m ^ sum) & (g.m ^ sum) & Fix24_msb )
  305.     f.overflow(sum);
  306.   return sum;
  307. }
  308.  
  309. inline Fix24 operator-(Fix24&  f, Fix24&  g) 
  310. {
  311.   long sum = f.m - g.m;
  312.   if ( (f.m ^ sum) & (-g.m ^ sum) & Fix24_msb )
  313.     f.overflow(sum);
  314.   return sum;
  315. }
  316.  
  317. inline Fix24 operator*(Fix24& a, int b)     
  318.   return a.m * b; 
  319. }
  320.  
  321. inline Fix24 operator*(int b, Fix24& a)     
  322.   return a * b; 
  323. }
  324.  
  325. inline Fix24 operator<<(Fix24& a, int b)     
  326.   return a.m << b; 
  327. }
  328.  
  329. inline Fix24 operator>>(Fix24& a, int b)     
  330.   return (a.m >> b) & 0xffffff00L; 
  331. }
  332.  
  333. inline  Fix24&  Fix24:: operator+=(Fix24&  f)
  334.   return *this = *this + f; 
  335. }
  336.  
  337. inline Fix24&  Fix24:: operator-=(Fix24&  f)     
  338.   return *this = *this - f; 
  339. }
  340.  
  341. inline Fix24& Fix24::operator*=(Fix24& f)     
  342.   return *this = *this * f; 
  343. }
  344.  
  345. inline Fix24&  Fix24:: operator/=(Fix24&  f)     
  346.   return *this = *this / f; 
  347. }
  348.  
  349. inline Fix24&  Fix24:: operator<<=(int b)    
  350.   return *this = *this << b;
  351. }
  352.  
  353. inline Fix24&  Fix24:: operator>>=(int b)    
  354.   return *this = *this >> b;
  355. }
  356.  
  357. inline Fix24& Fix24::operator*=(int b)
  358.   return *this = *this * b; 
  359. }
  360.  
  361. inline int operator==(Fix24&  f, Fix24&  g)    
  362.   return f.m == g.m;
  363. }
  364.  
  365. inline int operator!=(Fix24&  f, Fix24&  g)    
  366.   return f.m != g.m;
  367. }
  368.  
  369. inline int operator>=(Fix24&  f, Fix24&  g)    
  370.   return f.m >= g.m;
  371. }
  372.  
  373. inline int operator<=(Fix24&  f, Fix24&  g)    
  374.   return f.m <= g.m;
  375. }
  376.  
  377. inline int operator>(Fix24&  f, Fix24&  g)    
  378.   return f.m > g.m;
  379. }
  380.  
  381. inline int operator<(Fix24&  f, Fix24&  g)    
  382.   return f.m < g.m;
  383. }
  384.  
  385. inline istream&  operator>>(istream& s, Fix24&  f)
  386.   double d;
  387.   s >> d; 
  388.   f = d; 
  389.   return s; 
  390. }
  391.  
  392. inline ostream&  operator<<(ostream& s, Fix24&  f)
  393.   return s << double(f);
  394. }
  395.  
  396. inline Fix48::~Fix48() {}
  397.  
  398. inline Fix48::Fix48(twolongs i)        
  399.   m = i;
  400. }
  401.  
  402. inline Fix48:: operator double()        
  403. /*
  404.  * Note: can't simply do Fix48_div_u * m.u + Fix48_div_l * m.l, because
  405.  * m.u is signed and m.l is unsigned.
  406.  */
  407.   return (m.u >= 0)? Fix48_div_u * m.u + Fix48_div_l * m.l :
  408.       (Fix48_div_u * ((unsigned long)(m.u & 0xffffff00)) 
  409.       + Fix48_div_l * m.l) - 2;
  410. }
  411.  
  412. inline Fix48::Fix48()                
  413.   m.u = 0;
  414.   m.l = 0;
  415. }
  416.  
  417. inline Fix48::Fix48(Fix48& f)        
  418.   m = f.m;
  419. }
  420.  
  421. inline Fix48::Fix48(Fix24&  f)    
  422.   m.u = f.m;
  423.   m.l = 0;
  424. }
  425.  
  426. inline Fix48::Fix48(double d)        
  427.   m = assign(d);
  428. }
  429.  
  430. inline Fix48& Fix48::operator=(Fix48& f)    
  431.   m = f.m;
  432.   return *this; 
  433. }
  434.  
  435. inline Fix48& Fix48::operator=(Fix24&  f)    
  436.   m.u = f.m;
  437.   m.l = 0;
  438.   return *this;
  439. }
  440.  
  441. inline Fix48& Fix48::operator=(double d)    
  442.   m = assign(d);
  443.   return *this; 
  444. }
  445.  
  446. inline twolongs& mantissa(Fix48& f)    
  447.   return f.m;
  448. }
  449.  
  450. inline double value(Fix48& f)        
  451.   return double(f);
  452. }
  453.  
  454. inline Fix48 Fix48::operator+()         
  455.   return m;
  456. }
  457.  
  458. inline Fix48 Fix48::operator-()         
  459.   twolongs n;
  460.   n.l = -m.l;
  461.   n.u = ~m.u + ((n.l ^ m.l) & Fix24_msb ? 0 : Fix24_lsb);
  462.   return Fix48(n);
  463. }
  464.  
  465. inline Fix48 operator*(int b, Fix48& a)     
  466.   return a * b; 
  467. }
  468.  
  469. inline Fix48& Fix48::operator+=(Fix48& f)     
  470.   return *this = *this + f;
  471. }
  472.  
  473. inline Fix48& Fix48::operator-=(Fix48& f)     
  474.   return *this = *this - f;
  475. }
  476.  
  477. inline Fix48& Fix48::operator*=(int b)    
  478.   return *this = *this * b;
  479. }
  480.  
  481. inline Fix48& Fix48::operator<<=(int b)    
  482.   return *this = *this << b;
  483. }
  484.  
  485. inline Fix48& Fix48::operator>>=(int b)    
  486.   return *this = *this >> b;
  487. }
  488.  
  489. inline int operator==(Fix48& f, Fix48& g)    
  490.   return f.m.u == g.m.u && f.m.l == g.m.l;
  491. }
  492.  
  493. inline int operator!=(Fix48& f, Fix48& g)    
  494.   return f.m.u != g.m.u || f.m.l != g.m.l;
  495. }
  496.  
  497. inline int operator>=(Fix48& f, Fix48& g)    
  498.   return f.m.u >= g.m.u || (f.m.u == g.m.u && f.m.l >= g.m.l);
  499. }
  500.  
  501. inline int operator<=(Fix48& f, Fix48& g)    
  502.   return f.m.u <= g.m.u || (f.m.u == g.m.u && f.m.l <= g.m.l);
  503. }
  504.  
  505. inline int operator>(Fix48& f, Fix48& g)    
  506.   return f.m.u > g.m.u || (f.m.u == g.m.u && f.m.l > g.m.l);
  507. }
  508.  
  509. inline int operator<(Fix48& f, Fix48& g)    
  510.   return f.m.u < g.m.u || (f.m.u == g.m.u && f.m.l < g.m.l);
  511. }
  512.  
  513. inline istream& operator>>(istream& s, Fix48& f)
  514.   double d;
  515.   s >> d; 
  516.   f = d; 
  517.   return s; 
  518. }
  519.  
  520. inline ostream& operator<<(ostream& s, Fix48& f)
  521.   return s << double(f);
  522. }
  523.  
  524. #endif
  525.